<?php
/*********************************************
 *  CPG Dragonfly™ CMS
 *********************************************
	Copyright © since 2010 by CPG-Nuke Dev Team
	http://dragonflycms.org

	Dragonfly is released under the terms and conditions
	of the GNU GPL version 2 or any later version
*/

namespace Poodle;

abstract class UserAgent
{
	public static function detect()
	{
		$ua = self::application();
		$ua->engine = self::engine();
		$ua->OS     = self::os();
		if (empty($ua->name) || empty($ua->engine->name) || empty($ua->OS->name))
		{
			try {
				\Poodle::getKernel()->SQL->TBL->log_ua->insert(array(
					'log_ua_name'=>substr($_SERVER['HTTP_USER_AGENT'],0,255),
					'log_ua_time'=>time()
				));
			} catch (\Exception $e) {}
			if (empty($ua->name)) { $ua->name = 'unknown'; }
			if (empty($ua->engine->name)) { $ua->engine->name = 'unknown'; }
			if (empty($ua->OS->name)) { $ua->OS->name = 'unknown'; }
		}
		return $ua;
	}

	private static function ua()
	{
		static $ua;
		return ($ua ? $ua : $ua = strtolower($_SERVER['HTTP_USER_AGENT']));
	}

	public static function engine()
	{
		static $engine = null;
		if (!$engine) {
			$engine = array('name'=>null, 'version'=>0);
			$ua = self::ua();
			if (preg_match('#(apachebench|dillo|gecko|khtml|presto|trident|up\.browser|webkit|evolution|outlook)[/\ ]([0-9]+(\.[0-9]+)?)#', $ua, $match)
			 || preg_match('#(msie|opera)[/\ ]([0-9]+(\.[0-9]+)?)#', $ua, $match))
			{
				if ('opera' === $match[1]) { $match[1] = 'presto';  $match[2] = 1; }
				if ('msie'  === $match[1]) { $match[1] = 'trident'; $match[2] = 3; }
				$engine = array('name' => $match[1], 'version' => floatval($match[2]));
			}
		}
		return (object)$engine;
	}

	public static function application()
	{
		/**
		 * epiphany, flock and galeon have "firefox" in their UA
		 * chimera is an on old name of camino
		 * cheshire, midori, omniweb, shiira and sunrise have "safari" in their UA
		 * We don't detect MyIE2, AOL and America Online branded versions of MSIE
		 * Sylera is a Japanese Gecko based browser
		 */
		static $app = null;
		if (!$app) {
			$app = array('name'=>null, 'version'=>0);
			$ua = self::ua();
			if (preg_match('#(irider|crazy|netcaptor|maxthon|avant|webtv|ubvision)#', $ua, $match)
			 || preg_match('#(elinks|opera|shiira|devontech|ibrowse|icab)#', $ua, $match)
			 || preg_match('#(epiphany|flock|galeon|cheshire|midori|omniweb)#', $ua, $match)
			 || preg_match('#(konqueror|voyager|links|lynx|w3m|dillo|netscape|thunderbird|camino|seamonkey|linspire|multizilla|k\-meleon|kazehakase|minimo)#', $ua, $match)
			 || preg_match('#(chrome|safari|firefox)(?:/([0-9\\.]+))?#', $ua, $match)
			 || preg_match('#(msie) (1?[0-9](\.[0-9])?)#', $ua, $match)
			 || preg_match('#(webwasher)#', $ua, $match))
			{
				if ('ubvision' === $match[1]) { $match[1] = 'ultrabrowser'; }
				$app['name'] = $match[1];
				if (!empty($match[2])) { $app['version'] = floatval($match[2]); }
				if ('safari' === $app['name'] && preg_match('#Version/([0-9\.]+)#', $ua, $match))
				{
					$app['version'] = floatval($match[1]);
				}
			}
			/**
			 * firebird and phoenix are old names for firefox
			 * bonecho, granparadiso, minefield are develop names for firefox
			 */
			else if (preg_match('#(firebird|phoenix|bonecho|granparadiso|minefield|shiretoko)#', $ua))
			{
				$app['name'] = 'firefox';
			}
			else if (preg_match('#^mozilla/5.+gecko/200#', $ua))
			{
				$app['name'] = 'mozilla';
			}
		}
		return (object)$app;
	}

	public static function os()
	{
		static $os = null;
		if (!$os) {
			$os = array('name'=>null, 'version'=>0);
			/**
			 * BSD = FreeBSD, OpenBSD, NetBSD, DesktopBSD, etc.
			 * Win = 95, 98, 2000, XP, Vista, Mobile, etc.
			 * Fedora
			 * Ubuntu
			 * SUSE
			 * Red Hat
			 * CentOS
			 * Debian
			 * Gentoo
			 */
			if (preg_match('#(win|mac|linux|bsd|sunos|syllable|irix|beos|os/2|aix|amiga|symbian|react|blackberry|iphone|javafx|palm|nintendo|playstation)#', self::ua(), $match))
			{
				$os['name'] = ('win' === $match[1]) ? 'windows' : $match[1];
				/**
				 * Win98
				 * Windows 98
				 * Windows CE
				 * Windows NT 4.0
				 */
			}
		}
		return (object)$os;
	}

	public static function is_mobile()
	{
		static $mob = null;
		if (null !== $mob) { return $mob; }
		$ua = self::ua();
		return $mob = false !== strpos($ua, 'mobile')
		|| false !== strpos($ua, 'android')
		|| false !== strpos($ua, 'iphone')

		|| !empty($_SERVER['HTTP_X_OPERAMINI_PHONE'])
		|| false !== strpos(strtolower($_SERVER['HTTP_ACCEPT']), '/vnd.wap.') // xhtml+xml | wml
		|| false !== strpos($ua, 'symbian')
		|| false !== strpos($ua, 'windows ce')
		|| false !== strpos($ua, 'epoc')
		|| false !== strpos($ua, 'opera mini')
		|| false !== strpos($ua, 'opera mobi')
		|| false !== strpos($ua, 'minimo')
		|| false !== strpos($ua, 'nitro')
		|| false !== strpos($ua, 'j2me')
		|| false !== strpos($ua, 'midp-')
		|| false !== strpos($ua, 'cldc-')
		|| false !== strpos($ua, 'netfront')
		|| false !== strpos($ua, 'mot')
		|| false !== strpos($ua, 'up.browser')
		|| false !== strpos($ua, 'up.link')
		|| false !== strpos($ua, 'sony')
		|| false !== strpos($ua, 'nokia')
		|| false !== strpos($ua, 'samsung')
		|| false !== strpos($ua, 'audiovox')
		|| false !== strpos($ua, 'blackberry')
		|| false !== strpos($ua, 'ericsson')
		|| false !== strpos($ua, 'panasonic')
		|| false !== strpos($ua, 'philips')
		|| false !== strpos($ua, 'sanyo')
		|| false !== strpos($ua, 'sharp')
		|| false !== strpos($ua, 'sie-')
		|| false !== strpos($ua, 'portalmmm')
		|| false !== strpos($ua, 'blazer')
		|| false !== strpos($ua, 'avantgo')
		|| false !== strpos($ua, 'danger')
		|| false !== strpos($ua, 'palm')
		|| false !== strpos($ua, 'series60')
		|| false !== strpos($ua, 'palmsource')
		|| false !== strpos($ua, 'pocketpc')
		|| false !== strpos($ua, 'smartphone')
		|| false !== strpos($ua, 'rover')
		|| false !== strpos($ua, 'ipaq')
		|| false !== strpos($ua, 'au-mic')
		|| false !== strpos($ua, 'alcatel')
		|| false !== strpos($ua, 'ericy')
		|| false !== strpos($ua, 'vodafone/')
		|| false !== strpos($ua, 'wap1.')
		|| false !== strpos($ua, 'wap2.')
		|| false !== strpos($ua, 'portable')
		;
	}

	public static function is_bot($where=false)
	{
		static $bot = null;
		if (null !== $bot) { return $bot; }
		# Identify bot by UA
		$SQL = \Poodle::getKernel()->SQL;
		$result = $SQL->query('SELECT agent_name, agent_fullname FROM '.$SQL->TBL->security_agents
			.($where ? ' WHERE agent_name LIKE \''.$where.'%\'' : '')
			.' ORDER BY agent_name');
		while ($row = $result->fetch_row())
		{
			$row[1] = trim($row[1]);
			if (empty($row[1])) { continue; }
			if (false !== stripos($_SERVER['HTTP_USER_AGENT'], $row[1])) {
				$bot = $row[0];
			} else if ($bot && !$where) {
				break;
			}
		}
		$result->free();
		return ($bot === false) ? false : array('browser'=>$bot, 'engine'=>'bot');
	}

}
